home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Topik / Topik - Disk 14 - Useful Commands (19xx)(Topik Public Domain)(PD)[WB].zip / Topik - Disk 14 - Useful Commands (19xx)(Topik Public Domain)(PD)[WB].adf / C / Undelete.c < prev    next >
C/C++ Source or Header  |  1989-08-07  |  6KB  |  239 lines

  1. /* Undelete.c: A program to recover deleted files.
  2.  
  3.    This program will scan a disk for the given filename, and copy the file
  4. to another disk if found.  It is NOT case sensitive, and will find all
  5. copies of the file on the disk with the same name.
  6.  
  7.    When the file is copied, the number of the first block of the file is
  8. appended to the name to keep multiple copies from overwriting each other.
  9.  
  10. author: James Cooper Jr.
  11.     113-1B Collier Pl.
  12.     Cary, NC  27513
  13.  
  14. With thanks to:
  15.     Tom Wilcox
  16.     3047 Cameron Way
  17.     Santa Clara, CA 95051
  18.  
  19. for his fixdisk.c program.  This program is given to the public domain, but
  20. please keep the credits intact.
  21.  
  22. First Version:    July, 1986    (It works!)
  23. Second Version: March, 1988    (Added ability to specify destination path)
  24. */
  25.  
  26. #include <exec/types.h>
  27. #include <exec/nodes.h>
  28. #include <exec/lists.h>
  29. #include <exec/memory.h>
  30. #include <exec/interrupts.h>
  31. #include <exec/ports.h>
  32. #include <exec/libraries.h>
  33. #include <exec/io.h>
  34. #include <exec/tasks.h>
  35. #include <exec/execbase.h>
  36. #include <exec/devices.h>
  37. #include <devices/trackdisk.h>
  38. #include <ctype.h>
  39. #include <string.h>
  40. #include <stdio.h>
  41.  
  42. #include <proto/dos.h>
  43. #include <proto/exec.h>
  44.  
  45. #define BLOCKSIZE TD_SECTOR
  46.  
  47. struct MsgPort *diskport;
  48. struct IOExtTD *diskreq;
  49.  
  50. #define NAMELENGTH 408
  51. #define FILENAME   409
  52. #define TypeDATA    8L
  53.  
  54. struct DataBlock
  55. {
  56.   ULONG type, key, seqnum, size, next, checksum;
  57.   UBYTE data[BLOCKSIZE-24];
  58. };
  59.  
  60. struct DataBlock *Data = NULL;
  61.  
  62. int blocks = 0;
  63.  
  64. extern struct MsgPort *CreatePort();
  65. extern struct IORequest *CreateExtIO();
  66.  
  67. ULONG diskChangeCount;
  68.  
  69. char name[80];
  70. char *dest = "DF1:";
  71.  
  72. int ReadBlock(ULONG, char *);
  73. void MotorOn();
  74. void MotorOff();
  75. int CopyFile(LONG);
  76. int StrComp(char *, char *);
  77. void Cleanup(int);
  78. void main(int, char **);
  79.  
  80. int ReadBlock (Block, Kind)
  81. ULONG Block;
  82. char *Kind;
  83. {
  84.    diskreq->iotd_Req.io_Length = BLOCKSIZE;
  85.    diskreq->iotd_Req.io_Data = (APTR) Data;
  86.    diskreq->iotd_Req.io_Command = ETD_READ;
  87.    diskreq->iotd_Count = diskChangeCount;
  88.    diskreq->iotd_Req.io_Offset = BLOCKSIZE*Block;
  89.    DoIO(diskreq);
  90.  
  91.    if (diskreq->iotd_Req.io_Error != 0) {
  92.      printf("*** Can't read %s from block %ld; error %ld\n",
  93.          Kind,Block,diskreq->iotd_Req.io_Error);
  94.      return (FALSE);
  95.    }
  96.    return (TRUE);
  97. }
  98.  
  99. void MotorOn()
  100. {
  101.     /* TURN ON DISK MOTOR ... old motor state is returned in io_Actual */
  102.     diskreq->iotd_Req.io_Length = 1;  /* 1 => motor is to be turned on */
  103.     diskreq->iotd_Req.io_Command = TD_MOTOR;   /* operate on the motor */
  104.     DoIO(diskreq);
  105. }
  106.  
  107. void MotorOff()
  108. {
  109.     diskreq->iotd_Req.io_Length = 0; /* 0 => motor is to be turned off */
  110.     diskreq->iotd_Req.io_Command = TD_MOTOR;   /* operate on the motor */
  111.     DoIO(diskreq);
  112. }
  113.  
  114. int CopyFile(FirstBlock)
  115. LONG FirstBlock;
  116. {
  117.    FILE *file;
  118.    LONG block = FirstBlock;
  119.  
  120.    printf ("\n\n");
  121.  
  122.    sprintf (name, "%s%s.%ld", dest, &Data->data [FILENAME], block);
  123.    printf ("Writing file %s\n", name);
  124.  
  125.    if ((file = fopen (name, "w")) == NULL)
  126.    {
  127.        printf ("Cannot open %s\n\n", name);
  128.        return (0);
  129.    }
  130.  
  131.    for (block = FirstBlock; block != 0; block = Data->next)
  132.    {
  133.      if (!ReadBlock (block, "file data")) break;
  134.  
  135.      if (fwrite (Data->data, Data->size, 1, file) != 1)
  136.     printf ("*** Can't write data block %ld from disk block %ld\n",
  137.     Data->seqnum, block);
  138.      blocks = blocks-1;
  139.    }
  140.  
  141.    if (block==0) { printf ("File %s is complete\n\n", name); }
  142.    else printf ("File %s has been truncated\n\n", name);
  143.  
  144.    fclose (file);
  145. }
  146.  
  147. int StrComp(str1, str2)
  148. char *str1, *str2;
  149. {
  150.    int index = 0;
  151.  
  152.    while (1)
  153.    {
  154.       if (str1[index] == 0 && str2[index] == 0) return(0);
  155.       if (toupper(str1[index]) != toupper(str2[index])) return(-1);
  156.       index++;
  157.    }
  158. }
  159.  
  160. void Cleanup(code)
  161. int code;
  162. {
  163.   MotorOff();
  164.   if (diskreq) {
  165.     CloseDevice(diskreq);
  166.     DeleteExtIO(diskreq, sizeof(struct IOExtTD));
  167.   }
  168.   if (diskport) DeletePort(diskport);
  169.   if (Data) FreeMem(Data,BLOCKSIZE);
  170.   exit(code);
  171. }
  172.  
  173. void main(argc, argv)
  174. int argc;
  175. char **argv;
  176. {
  177.   LONG block;
  178.   char *lookedfor;
  179.  
  180.   if ((argc < 2) || (argv[1][0] == '?')) {
  181.     printf("Usage: Undelete <filename> [<destination path>]\n");
  182.     printf("(default destination path is 'DF1:')\n");
  183.     exit(0);
  184.   }
  185.  
  186.   lookedfor = argv[1];
  187.   if (argv[2]) {
  188.     if (argv[2][strlen(argv[2])-1] != '/' &&
  189.     argv[2][strlen(argv[2])-1] != ':') {
  190.       printf("%s is an invalid path!  (Must end with ':' or '/')\n",argv[2]);
  191.       exit(10);
  192.     }
  193.     dest = argv[2];
  194.   }
  195.  
  196.   if ((Data = (struct DataBlock *)AllocMem(BLOCKSIZE,MEMF_CHIP)) == NULL)
  197.     exit(11);
  198.  
  199.   if ((diskport = CreatePort(0,0)) == 0) Cleanup(12);    /* error */
  200.  
  201.   /* make an io request block for communicating with the disk */
  202.   diskreq = (struct IOExtTD *)CreateExtIO(diskport,sizeof(struct IOExtTD));
  203.  
  204.   if (diskreq == 0) Cleanup(13);
  205.  
  206.   /* open the device for access, unit 0 is builtin drive */
  207.   if (OpenDevice(TD_NAME,0,diskreq,0)) Cleanup(14);
  208.  
  209.   printf ("Put disk with deleted file in INTERNAL drive.\n");
  210.   printf ("(Cancel the requester if the disk is unreadable.)\n");
  211.   printf ("Press RETURN to begin.\n");
  212.  
  213.   getchar();
  214.  
  215.   /* now get the disk change value */
  216.   diskreq->iotd_Req.io_Command = TD_CHANGENUM;
  217.   DoIO(diskreq);
  218.   diskChangeCount = diskreq->iotd_Req.io_Actual;
  219.  
  220.   printf("Scanning disk for %s...\n", lookedfor);
  221.  
  222.   for (block = 0; block < 1760; block++) {
  223.     if (ReadBlock(block, "information") && Data->type == TypeDATA) {
  224.       blocks++;
  225.       if (Data->seqnum == 1) {
  226.     if (ReadBlock(Data->key, "file header")) {
  227.       Data->data [FILENAME + Data->data [NAMELENGTH]] = 0;
  228.       sprintf (name, "%s", &Data->data [FILENAME]);
  229.     } else
  230.       name[0] = 0;
  231.     printf("Name = %s\x9bK\r", name);
  232.     if (StrComp(name, lookedfor) == 0) CopyFile (block);
  233.       }
  234.     }
  235.   }
  236.   printf ("\n\nAll disk blocks have been scanned.\n");
  237.   Cleanup(0);
  238. }
  239.